package svc

import (
	"github.com/apache/rocketmq-client-go/v2"
	"github.com/go-redis/redis/v8"
	"github.com/xxl-job/xxl-job-executor-go"
	"github.com/zeromicro/go-zero/core/logx"
	"github.com/zeromicro/go-zero/zrpc"
	"go-zero-project/services/order/rpc/orderrpc"
	"go-zero-project/services/product/rpc/productrpc"
	"go-zero-project/services/user/api/internal/config"
	"go-zero-project/services/user/api/internal/initialize/mq/producer"
	initRedis "go-zero-project/services/user/api/internal/initialize/redis"
	initXxl "go-zero-project/services/user/api/internal/initialize/xxl"
	"go-zero-project/services/user/rpc/userrpc"
)

type ServiceContext struct {
	Config           config.Config
	UserCenterClient userrpc.UserRpc
	OrderRpcClient   orderrpc.OrderRpc
	ProductRpcClient productrpc.ProductRpc
	RedisClient      *redis.Client
	XxlExecutor      xxl.Executor
	DefaultProducer  rocketmq.Producer
	TransProducer    rocketmq.TransactionProducer
}

func NewServiceContext(c config.Config) *ServiceContext {
	serviceContext := &ServiceContext{
		Config: c,
	}
	// 1.init redis
	redisClient, redisErr := initRedis.InitRedis(c.Redis)
	if redisErr != nil {
		logx.Error(redisErr)
		return serviceContext
	}
	serviceContext.RedisClient = redisClient
	// 2.init xxl job
	executor, err := initXxl.InitXxlJob(c)
	if err != nil {
		logx.Error(err)
		return serviceContext
	}
	serviceContext.XxlExecutor = executor
	// 3.init mq
	defaultProducer, initMqErr := producer.InitDefaultProducer(c.MqConf)
	if initMqErr != nil {
		logx.Error(initMqErr)
		return serviceContext
	}
	serviceContext.DefaultProducer = defaultProducer
	transProducer, err := producer.InitTransProducer(c.MqConf)
	if err != nil {
		logx.Error(initMqErr)
		return serviceContext
	}
	serviceContext.TransProducer = transProducer
	// 4.init rpc interface
	// 4.1 init user rpc interface ...
	userClientConf := zrpc.RpcClientConf{}
	userClientConf.Target = c.UserRpc.Target
	userClientConf.NonBlock = true
	userClientConf.Timeout = 3000
	// 开启自适应限流
	userClientConf.Middlewares.Breaker = true
	// 开启全链路追踪
	userClientConf.Middlewares.Trace = true
	userClient := zrpc.MustNewClient(userClientConf)
	serviceContext.UserCenterClient = userrpc.NewUserRpc(userClient)
	// 4.2 init order rpc interface ...
	orderRpcConf := zrpc.RpcClientConf{}
	orderRpcConf.Target = c.OrderRpc.Target
	orderRpcConf.NonBlock = true
	orderRpcConf.Timeout = 3000
	// 开启自适应限流
	orderRpcConf.Middlewares.Breaker = true
	// 开启全链路追踪
	orderRpcConf.Middlewares.Trace = true
	orderClient := zrpc.MustNewClient(orderRpcConf)
	orderRpc := orderrpc.NewOrderRpc(orderClient)
	serviceContext.OrderRpcClient = orderRpc
	// 4.3 init product rpc interface ...
	productRpcConf := zrpc.RpcClientConf{}
	productRpcConf.Target = c.ProductRpc.Target
	productRpcConf.NonBlock = true
	productRpcConf.Timeout = 3000
	// 开启自适应限流
	productRpcConf.Middlewares.Breaker = true
	// 开启全链路追踪
	productRpcConf.Middlewares.Trace = true
	productRpcClient := zrpc.MustNewClient(productRpcConf)
	productRpc := productrpc.NewProductRpc(productRpcClient)
	serviceContext.ProductRpcClient = productRpc
	return serviceContext
}
